package com.github.bryx.workflow.command.executor;

import com.github.bryx.workflow.command.CloseWorkflowInstanceCommand;
import com.github.bryx.workflow.command.FetchTaskConfigCommand;
import com.github.bryx.workflow.domain.*;
import com.github.bryx.workflow.dto.runtime.UpdateWorkflowInstanceDto;
import com.github.bryx.workflow.dto.runtime.UpdateWorkflowTaskInstanceDto;
import com.github.bryx.workflow.dto.runtime.UpdateWorkflowTimerJobDto;
import com.github.bryx.workflow.event.WorkflowCloseEvent;
import com.github.bryx.workflow.handler.WorkflowInstanceAware;
import com.github.bryx.workflow.service.WorkflowBuildTimeService;
import com.github.bryx.workflow.service.WorkflowRuntimeService;
import com.github.bryx.workflow.service.process.ProcessService;
import com.github.bryx.workflow.util.StringUtil;
import com.github.bryx.workflow.util.WorkflowEngineUtil;
import com.google.common.base.Functions;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import lombok.SneakyThrows;
import net.sf.jsqlparser.statement.select.Fetch;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @Author jameswu
 * @Date 2021/6/10
 **/
@Component
@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class FetchTaskConfigCommandExecutor extends CommandExecutor<Map<String, WorkflowDefProcessConfig.UserTaskConfig>> {

    @Autowired
    WorkflowBuildTimeService workflowBuildTimeService;

    @Autowired
    WorkflowRuntimeService workflowRuntimeService;


    @SneakyThrows
    @Override
    @Transactional
    public Map<String, WorkflowDefProcessConfig.UserTaskConfig> run() {
        FetchTaskConfigCommand command = this.getCommand().as(FetchTaskConfigCommand.class);

        WorkflowInstanceAware workflowInstanceAware;
        WorkflowDefRev workflowDefRev;
        Map<String, WorkflowDefProcessConfig.UserTaskConfig> userTaskConfigMap = Maps.newHashMap();
        if (StringUtil.isEmpty(command.getWorkflowInstanceId())){
            // 如果发起时，则获取start节点配置
            WorkflowDef workflowDef = workflowBuildTimeService.query().getWorkflowDefByProcessDefKey(this.getProcessDefKey());
            workflowDefRev = workflowBuildTimeService.query().getLatestEnabledWorkflowDefRev(workflowDef.getId());
            WorkflowDefProcessConfig.UserTaskConfig userTaskConfig = workflowDefRev.getProcessConfig().getUserTasks().get(WorkflowDefProcessConfig.UserTaskConfig.START_NODE_DEF_ID);
            userTaskConfig.setUserActions(this.getWorkflowInstanceAware().userActionsOnTask(this.getProcessDefKey(), command.getUserId(), null, userTaskConfig));
            userTaskConfigMap.put(WorkflowDefProcessConfig.UserTaskConfig.START_NODE_DEF_ID, userTaskConfig);
        }else{
            WorkflowInstance workflowInstance = workflowRuntimeService.query().getWorkflowInstanceById(command.getWorkflowInstanceId());
            workflowDefRev = workflowBuildTimeService.query().getWorkflowDefRevById(workflowInstance.getDefRevId());
            if (workflowInstance.getStatus().equals(WorkflowInstance.WorkflowInstanceStatus.ONGOING)){
                // 还在运行的流程，返回节点上的配置
                List<WorkflowTaskInstance> runningWorkflowTaskInstances = workflowRuntimeService.query().getRunningWorkflowTaskInstances(command.getWorkflowInstanceId());
                runningWorkflowTaskInstances.forEach(task->{
                    WorkflowDefProcessConfig.UserTaskConfig userTaskConfig = workflowDefRev.getProcessConfig().getUserTasks().get(task.getProcessTaskDefId());
                    userTaskConfig.setUserActions(this.getWorkflowInstanceAware().userActionsOnTask(this.getProcessDefKey(), command.getUserId(), task, userTaskConfig));
                    userTaskConfigMap.put(task.getProcessTaskDefId(), userTaskConfig);
                });
            }else{
                // 结束的流程，返回end节点配置
                WorkflowDefProcessConfig.UserTaskConfig userTaskConfig = workflowDefRev.getProcessConfig().getUserTasks().get(WorkflowDefProcessConfig.UserTaskConfig.END_NODE_DEF_ID);
                userTaskConfig.setUserActions(this.getWorkflowInstanceAware().userActionsOnTask(this.getProcessDefKey(), command.getUserId(), null, userTaskConfig));
                userTaskConfigMap.put(WorkflowDefProcessConfig.UserTaskConfig.END_NODE_DEF_ID, userTaskConfig);
            }
        }
        // set form config
        Map<String, WorkflowDefField> fieldIdToFormFields = workflowDefRev.getProcessConfig().getForm().getFields().stream().collect(Collectors.toMap(WorkflowDefField::getId, Functions.identity()));
        userTaskConfigMap.forEach((taskDefId, userTaskConfig)->{
            userTaskConfig.getForm().getFields().forEach(field->{
                WorkflowDefField workflowFormField = fieldIdToFormFields.get(field.getId());
                BeanUtils.copyProperties(workflowFormField, field, WorkflowEngineUtil.getNamesOfNonNullProperty(field));
                field.setValue(null);
            });
        });
        return userTaskConfigMap;
    }
}
